package com.weedsdream.app.function

import androidx.compose.ui.geometry.Offset
import kotlin.math.abs

/**射线法：判断点是否在多边形内
 * @param point 要判断的坐标点
 * @param geoPoints 多边形顶点集合
 * @return true-点在多边形内*/
fun pointInPolygon(point: Offset, geoPoints: List<Offset>): Boolean {
    if (geoPoints.size < 3) return false//无法构成多边形
    var intersections = 0
    for (i in geoPoints.indices) {
        val p1 = geoPoints[i]
        val p2 = geoPoints[(i + 1) % geoPoints.size]
        if (isIntersecting(point, p1, p2)) intersections++// 检查射线是否与边相交
    }
    // 如果交点数量为奇数，则点在多边形内
    return intersections % 2 == 1
}

/**浮点计算误差*/
private const val inaccuracy = 0.01

/**point向上(x=0)的水平射线是否与边相交
 * @param pa 发出射线的点
 * @param p1 边的一端点
 * @param p2 边的一端点
 * @return true 相交*/
private fun isIntersecting(pa: Offset, p1: Offset, p2: Offset): Boolean {
    if (abs(p1.x - p2.x) < inaccuracy) return false //线段与射线垂直，必不相交
    val k12 = (p2.y - p1.y) / (p2.x - p1.x)//p1p2线斜率
    val c12 = p1.y - k12 * p1.x //p1p2线截距
    val x = pa.x//垂直x轴射线，x轴为恒定值
    val y = k12 * x + c12//射线与线段在的两条直线的交点

    return if (y < pa.y) false//不在射线方向
    else if (x < minOf(p1.x, p2.x) || x > maxOf(p1.x, p2.x)) false// 交点不在线段x范围内
    else if (y < minOf(p1.y, p2.y) || y > maxOf(p1.y, p2.y)) false//不在线段y范围
    else true
}